home *** CD-ROM | disk | FTP | other *** search
/ PC World 2007 March / PCWorld_2007-03_cd.bin / domacnost a kancelar / scribus / scribus-1.3.3.7-win32-install.exe / lib / compiler / pycodegen.py < prev    next >
Text File  |  2004-08-23  |  47KB  |  1,480 lines

  1. import imp
  2. import os
  3. import marshal
  4. import struct
  5. import sys
  6. import types
  7. from cStringIO import StringIO
  8.  
  9. from compiler import ast, parse, walk, syntax
  10. from compiler import pyassem, misc, future, symbols
  11. from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
  12. from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\
  13.      CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION
  14. from compiler.pyassem import TupleArg
  15.  
  16. # XXX The version-specific code can go, since this code only works with 2.x.
  17. # Do we have Python 1.x or Python 2.x?
  18. try:
  19.     VERSION = sys.version_info[0]
  20. except AttributeError:
  21.     VERSION = 1
  22.  
  23. callfunc_opcode_info = {
  24.     # (Have *args, Have **args) : opcode
  25.     (0,0) : "CALL_FUNCTION",
  26.     (1,0) : "CALL_FUNCTION_VAR",
  27.     (0,1) : "CALL_FUNCTION_KW",
  28.     (1,1) : "CALL_FUNCTION_VAR_KW",
  29. }
  30.  
  31. LOOP = 1
  32. EXCEPT = 2
  33. TRY_FINALLY = 3
  34. END_FINALLY = 4
  35.  
  36. def compileFile(filename, display=0):
  37.     f = open(filename, 'U')
  38.     buf = f.read()
  39.     f.close()
  40.     mod = Module(buf, filename)
  41.     try:
  42.         mod.compile(display)
  43.     except SyntaxError:
  44.         raise
  45.     else:
  46.         f = open(filename + "c", "wb")
  47.         mod.dump(f)
  48.         f.close()
  49.  
  50. def compile(source, filename, mode, flags=None, dont_inherit=None):
  51.     """Replacement for builtin compile() function"""
  52.     if flags is not None or dont_inherit is not None:
  53.         raise RuntimeError, "not implemented yet"
  54.  
  55.     if mode == "single":
  56.         gen = Interactive(source, filename)
  57.     elif mode == "exec":
  58.         gen = Module(source, filename)
  59.     elif mode == "eval":
  60.         gen = Expression(source, filename)
  61.     else:
  62.         raise ValueError("compile() 3rd arg must be 'exec' or "
  63.                          "'eval' or 'single'")
  64.     gen.compile()
  65.     return gen.code
  66.  
  67. class AbstractCompileMode:
  68.  
  69.     mode = None # defined by subclass
  70.  
  71.     def __init__(self, source, filename):
  72.         self.source = source
  73.         self.filename = filename
  74.         self.code = None
  75.  
  76.     def _get_tree(self):
  77.         tree = parse(self.source, self.mode)
  78.         misc.set_filename(self.filename, tree)
  79.         syntax.check(tree)
  80.         return tree
  81.  
  82.     def compile(self):
  83.         pass # implemented by subclass
  84.  
  85.     def getCode(self):
  86.         return self.code
  87.  
  88. class Expression(AbstractCompileMode):
  89.  
  90.     mode = "eval"
  91.  
  92.     def compile(self):
  93.         tree = self._get_tree()
  94.         gen = ExpressionCodeGenerator(tree)
  95.         self.code = gen.getCode()
  96.  
  97. class Interactive(AbstractCompileMode):
  98.  
  99.     mode = "single"
  100.  
  101.     def compile(self):
  102.         tree = self._get_tree()
  103.         gen = InteractiveCodeGenerator(tree)
  104.         self.code = gen.getCode()
  105.  
  106. class Module(AbstractCompileMode):
  107.  
  108.     mode = "exec"
  109.  
  110.     def compile(self, display=0):
  111.         tree = self._get_tree()
  112.         gen = ModuleCodeGenerator(tree)
  113.         if display:
  114.             import pprint
  115.             print pprint.pprint(tree)
  116.         self.code = gen.getCode()
  117.  
  118.     def dump(self, f):
  119.         f.write(self.getPycHeader())
  120.         marshal.dump(self.code, f)
  121.  
  122.     MAGIC = imp.get_magic()
  123.  
  124.     def getPycHeader(self):
  125.         # compile.c uses marshal to write a long directly, with
  126.         # calling the interface that would also generate a 1-byte code
  127.         # to indicate the type of the value.  simplest way to get the
  128.         # same effect is to call marshal and then skip the code.
  129.         mtime = os.path.getmtime(self.filename)
  130.         mtime = struct.pack('<i', mtime)
  131.         return self.MAGIC + mtime
  132.  
  133. class LocalNameFinder:
  134.     """Find local names in scope"""
  135.     def __init__(self, names=()):
  136.         self.names = misc.Set()
  137.         self.globals = misc.Set()
  138.         for name in names:
  139.             self.names.add(name)
  140.  
  141.     # XXX list comprehensions and for loops
  142.  
  143.     def getLocals(self):
  144.         for elt in self.globals.elements():
  145.             if self.names.has_elt(elt):
  146.                 self.names.remove(elt)
  147.         return self.names
  148.  
  149.     def visitDict(self, node):
  150.         pass
  151.  
  152.     def visitGlobal(self, node):
  153.         for name in node.names:
  154.             self.globals.add(name)
  155.  
  156.     def visitFunction(self, node):
  157.         self.names.add(node.name)
  158.  
  159.     def visitLambda(self, node):
  160.         pass
  161.  
  162.     def visitImport(self, node):
  163.         for name, alias in node.names:
  164.             self.names.add(alias or name)
  165.  
  166.     def visitFrom(self, node):
  167.         for name, alias in node.names:
  168.             self.names.add(alias or name)
  169.  
  170.     def visitClass(self, node):
  171.         self.names.add(node.name)
  172.  
  173.     def visitAssName(self, node):
  174.         self.names.add(node.name)
  175.  
  176. def is_constant_false(node):
  177.     if isinstance(node, ast.Const):
  178.         if not node.value:
  179.             return 1
  180.     return 0
  181.  
  182. class CodeGenerator:
  183.     """Defines basic code generator for Python bytecode
  184.  
  185.     This class is an abstract base class.  Concrete subclasses must
  186.     define an __init__() that defines self.graph and then calls the
  187.     __init__() defined in this class.
  188.  
  189.     The concrete class must also define the class attributes
  190.     NameFinder, FunctionGen, and ClassGen.  These attributes can be
  191.     defined in the initClass() method, which is a hook for
  192.     initializing these methods after all the classes have been
  193.     defined.
  194.     """
  195.  
  196.     optimized = 0 # is namespace access optimized?
  197.     __initialized = None
  198.     class_name = None # provide default for instance variable
  199.  
  200.     def __init__(self):
  201.         if self.__initialized is None:
  202.             self.initClass()
  203.             self.__class__.__initialized = 1
  204.         self.checkClass()
  205.         self.locals = misc.Stack()
  206.         self.setups = misc.Stack()
  207.         self.last_lineno = None
  208.         self._setupGraphDelegation()
  209.         self._div_op = "BINARY_DIVIDE"
  210.  
  211.         # XXX set flags based on future features
  212.         futures = self.get_module().futures
  213.         for feature in futures:
  214.             if feature == "division":
  215.                 self.graph.setFlag(CO_FUTURE_DIVISION)
  216.                 self._div_op = "BINARY_TRUE_DIVIDE"
  217.             elif feature == "generators":
  218.                 self.graph.setFlag(CO_GENERATOR_ALLOWED)
  219.  
  220.     def initClass(self):
  221.         """This method is called once for each class"""
  222.  
  223.     def checkClass(self):
  224.         """Verify that class is constructed correctly"""
  225.         try:
  226.             assert hasattr(self, 'graph')
  227.             assert getattr(self, 'NameFinder')
  228.             assert getattr(self, 'FunctionGen')
  229.             assert getattr(self, 'ClassGen')
  230.         except AssertionError, msg:
  231.             intro = "Bad class construction for %s" % self.__class__.__name__
  232.             raise AssertionError, intro
  233.  
  234.     def _setupGraphDelegation(self):
  235.         self.emit = self.graph.emit
  236.         self.newBlock = self.graph.newBlock
  237.         self.startBlock = self.graph.startBlock
  238.         self.nextBlock = self.graph.nextBlock
  239.         self.setDocstring = self.graph.setDocstring
  240.  
  241.     def getCode(self):
  242.         """Return a code object"""
  243.         return self.graph.getCode()
  244.  
  245.     def mangle(self, name):
  246.         if self.class_name is not None:
  247.             return misc.mangle(name, self.class_name)
  248.         else:
  249.             return name
  250.  
  251.     def parseSymbols(self, tree):
  252.         s = symbols.SymbolVisitor()
  253.         walk(tree, s)
  254.         return s.scopes
  255.  
  256.     def get_module(self):
  257.         raise RuntimeError, "should be implemented by subclasses"
  258.  
  259.     # Next five methods handle name access
  260.  
  261.     def isLocalName(self, name):
  262.         return self.locals.top().has_elt(name)
  263.  
  264.     def storeName(self, name):
  265.         self._nameOp('STORE', name)
  266.  
  267.     def loadName(self, name):
  268.         self._nameOp('LOAD', name)
  269.  
  270.     def delName(self, name):
  271.         self._nameOp('DELETE', name)
  272.  
  273.     def _nameOp(self, prefix, name):
  274.         name = self.mangle(name)
  275.         scope = self.scope.check_name(name)
  276.         if scope == SC_LOCAL:
  277.             if not self.optimized:
  278.                 self.emit(prefix + '_NAME', name)
  279.             else:
  280.                 self.emit(prefix + '_FAST', name)
  281.         elif scope == SC_GLOBAL:
  282.             if not self.optimized:
  283.                 self.emit(prefix + '_NAME', name)
  284.             else:
  285.                 self.emit(prefix + '_GLOBAL', name)
  286.         elif scope == SC_FREE or scope == SC_CELL:
  287.             self.emit(prefix + '_DEREF', name)
  288.         else:
  289.             raise RuntimeError, "unsupported scope for var %s: %d" % \
  290.                   (name, scope)
  291.  
  292.     def _implicitNameOp(self, prefix, name):
  293.         """Emit name ops for names generated implicitly by for loops
  294.  
  295.         The interpreter generates names that start with a period or
  296.         dollar sign.  The symbol table ignores these names because
  297.         they aren't present in the program text.
  298.         """
  299.         if self.optimized:
  300.             self.emit(prefix + '_FAST', name)
  301.         else:
  302.             self.emit(prefix + '_NAME', name)
  303.  
  304.     # The set_lineno() function and the explicit emit() calls for
  305.     # SET_LINENO below are only used to generate the line number table.
  306.     # As of Python 2.3, the interpreter does not have a SET_LINENO
  307.     # instruction.  pyassem treats SET_LINENO opcodes as a special case.
  308.  
  309.     def set_lineno(self, node, force=False):
  310.         """Emit SET_LINENO if necessary.
  311.  
  312.         The instruction is considered necessary if the node has a
  313.         lineno attribute and it is different than the last lineno
  314.         emitted.
  315.  
  316.         Returns true if SET_LINENO was emitted.
  317.  
  318.         There are no rules for when an AST node should have a lineno
  319.         attribute.  The transformer and AST code need to be reviewed
  320.         and a consistent policy implemented and documented.  Until
  321.         then, this method works around missing line numbers.
  322.         """
  323.         lineno = getattr(node, 'lineno', None)
  324.         if lineno is not None and (lineno != self.last_lineno
  325.                                    or force):
  326.             self.emit('SET_LINENO', lineno)
  327.             self.last_lineno = lineno
  328.             return True
  329.         return False
  330.  
  331.     # The first few visitor methods handle nodes that generator new
  332.     # code objects.  They use class attributes to determine what
  333.     # specialized code generators to use.
  334.  
  335.     NameFinder = LocalNameFinder
  336.     FunctionGen = None
  337.     ClassGen = None
  338.  
  339.     def visitModule(self, node):
  340.         self.scopes = self.parseSymbols(node)
  341.         self.scope = self.scopes[node]
  342.         self.emit('SET_LINENO', 0)
  343.         if node.doc:
  344.             self.emit('LOAD_CONST', node.doc)
  345.             self.storeName('__doc__')
  346.         lnf = walk(node.node, self.NameFinder(), verbose=0)
  347.         self.locals.push(lnf.getLocals())
  348.         self.visit(node.node)
  349.         self.emit('LOAD_CONST', None)
  350.         self.emit('RETURN_VALUE')
  351.  
  352.     def visitExpression(self, node):
  353.         self.set_lineno(node)
  354.         self.scopes = self.parseSymbols(node)
  355.         self.scope = self.scopes[node]
  356.         self.visit(node.node)
  357.         self.emit('RETURN_VALUE')
  358.  
  359.     def visitFunction(self, node):
  360.         self._visitFuncOrLambda(node, isLambda=0)
  361.         if node.doc:
  362.             self.setDocstring(node.doc)
  363.         self.storeName(node.name)
  364.  
  365.     def visitLambda(self, node):
  366.         self._visitFuncOrLambda(node, isLambda=1)
  367.  
  368.     def _visitFuncOrLambda(self, node, isLambda=0):
  369.         if not isLambda and node.decorators:
  370.             for decorator in node.decorators.nodes:
  371.                 self.visit(decorator)
  372.             ndecorators = len(node.decorators.nodes)
  373.         else:
  374.             ndecorators = 0
  375.  
  376.         gen = self.FunctionGen(node, self.scopes, isLambda,
  377.                                self.class_name, self.get_module())
  378.         walk(node.code, gen)
  379.         gen.finish()
  380.         self.set_lineno(node)
  381.         for default in node.defaults:
  382.             self.visit(default)
  383.         frees = gen.scope.get_free_vars()
  384.         if frees:
  385.             for name in frees:
  386.                 self.emit('LOAD_CLOSURE', name)
  387.             self.emit('LOAD_CONST', gen)
  388.             self.emit('MAKE_CLOSURE', len(node.defaults))
  389.         else:
  390.             self.emit('LOAD_CONST', gen)
  391.             self.emit('MAKE_FUNCTION', len(node.defaults))
  392.  
  393.         for i in range(ndecorators):
  394.             self.emit('CALL_FUNCTION', 1)
  395.  
  396.     def visitClass(self, node):
  397.         gen = self.ClassGen(node, self.scopes,
  398.                             self.get_module())
  399.         walk(node.code, gen)
  400.         gen.finish()
  401.         self.set_lineno(node)
  402.         self.emit('LOAD_CONST', node.name)
  403.         for base in node.bases:
  404.             self.visit(base)
  405.         self.emit('BUILD_TUPLE', len(node.bases))
  406.         frees = gen.scope.get_free_vars()
  407.         for name in frees:
  408.             self.emit('LOAD_CLOSURE', name)
  409.         self.emit('LOAD_CONST', gen)
  410.         if frees:
  411.             self.emit('MAKE_CLOSURE', 0)
  412.         else:
  413.             self.emit('MAKE_FUNCTION', 0)
  414.         self.emit('CALL_FUNCTION', 0)
  415.         self.emit('BUILD_CLASS')
  416.         self.storeName(node.name)
  417.  
  418.     # The rest are standard visitor methods
  419.  
  420.     # The next few implement control-flow statements
  421.  
  422.     def visitIf(self, node):
  423.         end = self.newBlock()
  424.         numtests = len(node.tests)
  425.         for i in range(numtests):
  426.             test, suite = node.tests[i]
  427.             if is_constant_false(test):
  428.                 # XXX will need to check generator stuff here
  429.                 continue
  430.             self.set_lineno(test)
  431.             self.visit(test)
  432.             nextTest = self.newBlock()
  433.             self.emit('JUMP_IF_FALSE', nextTest)
  434.             self.nextBlock()
  435.             self.emit('POP_TOP')
  436.             self.visit(suite)
  437.             self.emit('JUMP_FORWARD', end)
  438.             self.startBlock(nextTest)
  439.             self.emit('POP_TOP')
  440.         if node.else_:
  441.             self.visit(node.else_)
  442.         self.nextBlock(end)
  443.  
  444.     def visitWhile(self, node):
  445.         self.set_lineno(node)
  446.  
  447.         loop = self.newBlock()
  448.         else_ = self.newBlock()
  449.  
  450.         after = self.newBlock()
  451.         self.emit('SETUP_LOOP', after)
  452.  
  453.         self.nextBlock(loop)
  454.         self.setups.push((LOOP, loop))
  455.  
  456.         self.set_lineno(node, force=True)
  457.         self.visit(node.test)
  458.         self.emit('JUMP_IF_FALSE', else_ or after)
  459.  
  460.         self.nextBlock()
  461.         self.emit('POP_TOP')
  462.         self.visit(node.body)
  463.         self.emit('JUMP_ABSOLUTE', loop)
  464.  
  465.         self.startBlock(else_) # or just the POPs if not else clause
  466.         self.emit('POP_TOP')
  467.         self.emit('POP_BLOCK')
  468.         self.setups.pop()
  469.         if node.else_:
  470.             self.visit(node.else_)
  471.         self.nextBlock(after)
  472.  
  473.     def visitFor(self, node):
  474.         start = self.newBlock()
  475.         anchor = self.newBlock()
  476.         after = self.newBlock()
  477.         self.setups.push((LOOP, start))
  478.  
  479.         self.set_lineno(node)
  480.         self.emit('SETUP_LOOP', after)
  481.         self.visit(node.list)
  482.         self.emit('GET_ITER')
  483.  
  484.         self.nextBlock(start)
  485.         self.set_lineno(node, force=1)
  486.         self.emit('FOR_ITER', anchor)
  487.         self.visit(node.assign)
  488.         self.visit(node.body)
  489.         self.emit('JUMP_ABSOLUTE', start)
  490.         self.nextBlock(anchor)
  491.         self.emit('POP_BLOCK')
  492.         self.setups.pop()
  493.         if node.else_:
  494.             self.visit(node.else_)
  495.         self.nextBlock(after)
  496.  
  497.     def visitBreak(self, node):
  498.         if not self.setups:
  499.             raise SyntaxError, "'break' outside loop (%s, %d)" % \
  500.                   (node.filename, node.lineno)
  501.         self.set_lineno(node)
  502.         self.emit('BREAK_LOOP')
  503.  
  504.     def visitContinue(self, node):
  505.         if not self.setups:
  506.             raise SyntaxError, "'continue' outside loop (%s, %d)" % \
  507.                   (node.filename, node.lineno)
  508.         kind, block = self.setups.top()
  509.         if kind == LOOP:
  510.             self.set_lineno(node)
  511.             self.emit('JUMP_ABSOLUTE', block)
  512.             self.nextBlock()
  513.         elif kind == EXCEPT or kind == TRY_FINALLY:
  514.             self.set_lineno(node)
  515.             # find the block that starts the loop
  516.             top = len(self.setups)
  517.             while top > 0:
  518.                 top = top - 1
  519.                 kind, loop_block = self.setups[top]
  520.                 if kind == LOOP:
  521.                     break
  522.             if kind != LOOP:
  523.                 raise SyntaxError, "'continue' outside loop (%s, %d)" % \
  524.                       (node.filename, node.lineno)
  525.             self.emit('CONTINUE_LOOP', loop_block)
  526.             self.nextBlock()
  527.         elif kind == END_FINALLY:
  528.             msg = "'continue' not allowed inside 'finally' clause (%s, %d)"
  529.             raise SyntaxError, msg % (node.filename, node.lineno)
  530.  
  531.     def visitTest(self, node, jump):
  532.         end = self.newBlock()
  533.         for child in node.nodes[:-1]:
  534.             self.visit(child)
  535.             self.emit(jump, end)
  536.             self.nextBlock()
  537.             self.emit('POP_TOP')
  538.         self.visit(node.nodes[-1])
  539.         self.nextBlock(end)
  540.  
  541.     def visitAnd(self, node):
  542.         self.visitTest(node, 'JUMP_IF_FALSE')
  543.  
  544.     def visitOr(self, node):
  545.         self.visitTest(node, 'JUMP_IF_TRUE')
  546.  
  547.     def visitCompare(self, node):
  548.         self.visit(node.expr)
  549.         cleanup = self.newBlock()
  550.         for op, code in node.ops[:-1]:
  551.             self.visit(code)
  552.             self.emit('DUP_TOP')
  553.             self.emit('ROT_THREE')
  554.             self.emit('COMPARE_OP', op)
  555.             self.emit('JUMP_IF_FALSE', cleanup)
  556.             self.nextBlock()
  557.             self.emit('POP_TOP')
  558.         # now do the last comparison
  559.         if node.ops:
  560.             op, code = node.ops[-1]
  561.             self.visit(code)
  562.             self.emit('COMPARE_OP', op)
  563.         if len(node.ops) > 1:
  564.             end = self.newBlock()
  565.             self.emit('JUMP_FORWARD', end)
  566.             self.startBlock(cleanup)
  567.             self.emit('ROT_TWO')
  568.             self.emit('POP_TOP')
  569.             self.nextBlock(end)
  570.  
  571.     # list comprehensions
  572.     __list_count = 0
  573.  
  574.     def visitListComp(self, node):
  575.         self.set_lineno(node)
  576.         # setup list
  577.         append = "$append%d" % self.__list_count
  578.         self.__list_count = self.__list_count + 1
  579.         self.emit('BUILD_LIST', 0)
  580.         self.emit('DUP_TOP')
  581.         self.emit('LOAD_ATTR', 'append')
  582.         self._implicitNameOp('STORE', append)
  583.  
  584.         stack = []
  585.         for i, for_ in zip(range(len(node.quals)), node.quals):
  586.             start, anchor = self.visit(for_)
  587.             cont = None
  588.             for if_ in for_.ifs:
  589.                 if cont is None:
  590.                     cont = self.newBlock()
  591.                 self.visit(if_, cont)
  592.             stack.insert(0, (start, cont, anchor))
  593.  
  594.         self._implicitNameOp('LOAD', append)
  595.         self.visit(node.expr)
  596.         self.emit('CALL_FUNCTION', 1)
  597.         self.emit('POP_TOP')
  598.  
  599.         for start, cont, anchor in stack:
  600.             if cont:
  601.                 skip_one = self.newBlock()
  602.                 self.emit('JUMP_FORWARD', skip_one)
  603.                 self.startBlock(cont)
  604.                 self.emit('POP_TOP')
  605.                 self.nextBlock(skip_one)
  606.             self.emit('JUMP_ABSOLUTE', start)
  607.             self.startBlock(anchor)
  608.         self._implicitNameOp('DELETE', append)
  609.  
  610.         self.__list_count = self.__list_count - 1
  611.  
  612.     def visitListCompFor(self, node):
  613.         start = self.newBlock()
  614.         anchor = self.newBlock()
  615.  
  616.         self.visit(node.list)
  617.         self.emit('GET_ITER')
  618.         self.nextBlock(start)
  619.         self.set_lineno(node, force=True)
  620.         self.emit('FOR_ITER', anchor)
  621.         self.nextBlock()
  622.         self.visit(node.assign)
  623.         return start, anchor
  624.  
  625.     def visitListCompIf(self, node, branch):
  626.         self.set_lineno(node, force=True)
  627.         self.visit(node.test)
  628.         self.emit('JUMP_IF_FALSE', branch)
  629.         self.newBlock()
  630.         self.emit('POP_TOP')
  631.  
  632.     def visitGenExpr(self, node):
  633.         gen = GenExprCodeGenerator(node, self.scopes, self.class_name,
  634.                                    self.get_module())
  635.         walk(node.code, gen)
  636.         gen.finish()
  637.         self.set_lineno(node)
  638.         frees = gen.scope.get_free_vars()
  639.         if frees:
  640.             for name in frees:
  641.                 self.emit('LOAD_CLOSURE', name)
  642.             self.emit('LOAD_CONST', gen)
  643.             self.emit('MAKE_CLOSURE', 0)
  644.         else:
  645.             self.emit('LOAD_CONST', gen)
  646.             self.emit('MAKE_FUNCTION', 0)
  647.  
  648.         # precomputation of outmost iterable
  649.         self.visit(node.code.quals[0].iter)
  650.         self.emit('GET_ITER')
  651.         self.emit('CALL_FUNCTION', 1)
  652.  
  653.     def visitGenExprInner(self, node):
  654.         self.set_lineno(node)
  655.         # setup list
  656.  
  657.         stack = []
  658.         for i, for_ in zip(range(len(node.quals)), node.quals):
  659.             start, anchor = self.visit(for_)
  660.             cont = None
  661.             for if_ in for_.ifs:
  662.                 if cont is None:
  663.                     cont = self.newBlock()
  664.                 self.visit(if_, cont)
  665.             stack.insert(0, (start, cont, anchor))
  666.  
  667.         self.visit(node.expr)
  668.         self.emit('YIELD_VALUE')
  669.  
  670.         for start, cont, anchor in stack:
  671.             if cont:
  672.                 skip_one = self.newBlock()
  673.                 self.emit('JUMP_FORWARD', skip_one)
  674.                 self.startBlock(cont)
  675.                 self.emit('POP_TOP')
  676.                 self.nextBlock(skip_one)
  677.             self.emit('JUMP_ABSOLUTE', start)
  678.             self.startBlock(anchor)
  679.         self.emit('LOAD_CONST', None)
  680.  
  681.     def visitGenExprFor(self, node):
  682.         start = self.newBlock()
  683.         anchor = self.newBlock()
  684.  
  685.         if node.is_outmost:
  686.             self.loadName('[outmost-iterable]')
  687.         else:
  688.             self.visit(node.iter)
  689.             self.emit('GET_ITER')
  690.  
  691.         self.nextBlock(start)
  692.         self.set_lineno(node, force=True)
  693.         self.emit('FOR_ITER', anchor)
  694.         self.nextBlock()
  695.         self.visit(node.assign)
  696.         return start, anchor
  697.  
  698.     def visitGenExprIf(self, node, branch):
  699.         self.set_lineno(node, force=True)
  700.         self.visit(node.test)
  701.         self.emit('JUMP_IF_FALSE', branch)
  702.         self.newBlock()
  703.         self.emit('POP_TOP')
  704.  
  705.     # exception related
  706.  
  707.     def visitAssert(self, node):
  708.         # XXX would be interesting to implement this via a
  709.         # transformation of the AST before this stage
  710.         if __debug__:
  711.             end = self.newBlock()
  712.             self.set_lineno(node)
  713.             # XXX AssertionError appears to be special case -- it is always
  714.             # loaded as a global even if there is a local name.  I guess this
  715.             # is a sort of renaming op.
  716.             self.nextBlock()
  717.             self.visit(node.test)
  718.             self.emit('JUMP_IF_TRUE', end)
  719.             self.nextBlock()
  720.             self.emit('POP_TOP')
  721.             self.emit('LOAD_GLOBAL', 'AssertionError')
  722.             if node.fail:
  723.                 self.visit(node.fail)
  724.                 self.emit('RAISE_VARARGS', 2)
  725.             else:
  726.                 self.emit('RAISE_VARARGS', 1)
  727.             self.nextBlock(end)
  728.             self.emit('POP_TOP')
  729.  
  730.     def visitRaise(self, node):
  731.         self.set_lineno(node)
  732.         n = 0
  733.         if node.expr1:
  734.             self.visit(node.expr1)
  735.             n = n + 1
  736.         if node.expr2:
  737.             self.visit(node.expr2)
  738.             n = n + 1
  739.         if node.expr3:
  740.             self.visit(node.expr3)
  741.             n = n + 1
  742.         self.emit('RAISE_VARARGS', n)
  743.  
  744.     def visitTryExcept(self, node):
  745.         body = self.newBlock()
  746.         handlers = self.newBlock()
  747.         end = self.newBlock()
  748.         if node.else_:
  749.             lElse = self.newBlock()
  750.         else:
  751.             lElse = end
  752.         self.set_lineno(node)
  753.         self.emit('SETUP_EXCEPT', handlers)
  754.         self.nextBlock(body)
  755.         self.setups.push((EXCEPT, body))
  756.         self.visit(node.body)
  757.         self.emit('POP_BLOCK')
  758.         self.setups.pop()
  759.         self.emit('JUMP_FORWARD', lElse)
  760.         self.startBlock(handlers)
  761.  
  762.         last = len(node.handlers) - 1
  763.         for i in range(len(node.handlers)):
  764.             expr, target, body = node.handlers[i]
  765.             self.set_lineno(expr)
  766.             if expr:
  767.                 self.emit('DUP_TOP')
  768.                 self.visit(expr)
  769.                 self.emit('COMPARE_OP', 'exception match')
  770.                 next = self.newBlock()
  771.                 self.emit('JUMP_IF_FALSE', next)
  772.                 self.nextBlock()
  773.                 self.emit('POP_TOP')
  774.             self.emit('POP_TOP')
  775.             if target:
  776.                 self.visit(target)
  777.             else:
  778.                 self.emit('POP_TOP')
  779.             self.emit('POP_TOP')
  780.             self.visit(body)
  781.             self.emit('JUMP_FORWARD', end)
  782.             if expr:
  783.                 self.nextBlock(next)
  784.             else:
  785.                 self.nextBlock()
  786.             if expr: # XXX
  787.                 self.emit('POP_TOP')
  788.         self.emit('END_FINALLY')
  789.         if node.else_:
  790.             self.nextBlock(lElse)
  791.             self.visit(node.else_)
  792.         self.nextBlock(end)
  793.  
  794.     def visitTryFinally(self, node):
  795.         body = self.newBlock()
  796.         final = self.newBlock()
  797.         self.set_lineno(node)
  798.         self.emit('SETUP_FINALLY', final)
  799.         self.nextBlock(body)
  800.         self.setups.push((TRY_FINALLY, body))
  801.         self.visit(node.body)
  802.         self.emit('POP_BLOCK')
  803.         self.setups.pop()
  804.         self.emit('LOAD_CONST', None)
  805.         self.nextBlock(final)
  806.         self.setups.push((END_FINALLY, final))
  807.         self.visit(node.final)
  808.         self.emit('END_FINALLY')
  809.         self.setups.pop()
  810.  
  811.     # misc
  812.  
  813.     def visitDiscard(self, node):
  814.         self.set_lineno(node)
  815.         self.visit(node.expr)
  816.         self.emit('POP_TOP')
  817.  
  818.     def visitConst(self, node):
  819.         self.emit('LOAD_CONST', node.value)
  820.  
  821.     def visitKeyword(self, node):
  822.         self.emit('LOAD_CONST', node.name)
  823.         self.visit(node.expr)
  824.  
  825.     def visitGlobal(self, node):
  826.         # no code to generate
  827.         pass
  828.  
  829.     def visitName(self, node):
  830.         self.set_lineno(node)
  831.         self.loadName(node.name)
  832.  
  833.     def visitPass(self, node):
  834.         self.set_lineno(node)
  835.  
  836.     def visitImport(self, node):
  837.         self.set_lineno(node)
  838.         for name, alias in node.names:
  839.             if VERSION > 1:
  840.                 self.emit('LOAD_CONST', None)
  841.             self.emit('IMPORT_NAME', name)
  842.             mod = name.split(".")[0]
  843.             if alias:
  844.                 self._resolveDots(name)
  845.                 self.storeName(alias)
  846.             else:
  847.                 self.storeName(mod)
  848.  
  849.     def visitFrom(self, node):
  850.         self.set_lineno(node)
  851.         fromlist = map(lambda (name, alias): name, node.names)
  852.         if VERSION > 1:
  853.             self.emit('LOAD_CONST', tuple(fromlist))
  854.         self.emit('IMPORT_NAME', node.modname)
  855.         for name, alias in node.names:
  856.             if VERSION > 1:
  857.                 if name == '*':
  858.                     self.namespace = 0
  859.                     self.emit('IMPORT_STAR')
  860.                     # There can only be one name w/ from ... import *
  861.                     assert len(node.names) == 1
  862.                     return
  863.                 else:
  864.                     self.emit('IMPORT_FROM', name)
  865.                     self._resolveDots(name)
  866.                     self.storeName(alias or name)
  867.             else:
  868.                 self.emit('IMPORT_FROM', name)
  869.         self.emit('POP_TOP')
  870.  
  871.     def _resolveDots(self, name):
  872.         elts = name.split(".")
  873.         if len(elts) == 1:
  874.             return
  875.         for elt in elts[1:]:
  876.             self.emit('LOAD_ATTR', elt)
  877.  
  878.     def visitGetattr(self, node):
  879.         self.visit(node.expr)
  880.         self.emit('LOAD_ATTR', self.mangle(node.attrname))
  881.  
  882.     # next five implement assignments
  883.  
  884.     def visitAssign(self, node):
  885.         self.set_lineno(node)
  886.         self.visit(node.expr)
  887.         dups = len(node.nodes) - 1
  888.         for i in range(len(node.nodes)):
  889.             elt = node.nodes[i]
  890.             if i < dups:
  891.                 self.emit('DUP_TOP')
  892.             if isinstance(elt, ast.Node):
  893.                 self.visit(elt)
  894.  
  895.     def visitAssName(self, node):
  896.         if node.flags == 'OP_ASSIGN':
  897.             self.storeName(node.name)
  898.         elif node.flags == 'OP_DELETE':
  899.             self.set_lineno(node)
  900.             self.delName(node.name)
  901.         else:
  902.             print "oops", node.flags
  903.  
  904.     def visitAssAttr(self, node):
  905.         self.visit(node.expr)
  906.         if node.flags == 'OP_ASSIGN':
  907.             self.emit('STORE_ATTR', self.mangle(node.attrname))
  908.         elif node.flags == 'OP_DELETE':
  909.             self.emit('DELETE_ATTR', self.mangle(node.attrname))
  910.         else:
  911.             print "warning: unexpected flags:", node.flags
  912.             print node
  913.  
  914.     def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
  915.         if findOp(node) != 'OP_DELETE':
  916.             self.emit(op, len(node.nodes))
  917.         for child in node.nodes:
  918.             self.visit(child)
  919.  
  920.     if VERSION > 1:
  921.         visitAssTuple = _visitAssSequence
  922.         visitAssList = _visitAssSequence
  923.     else:
  924.         def visitAssTuple(self, node):
  925.             self._visitAssSequence(node, 'UNPACK_TUPLE')
  926.  
  927.         def visitAssList(self, node):
  928.             self._visitAssSequence(node, 'UNPACK_LIST')
  929.  
  930.     # augmented assignment
  931.  
  932.     def visitAugAssign(self, node):
  933.         self.set_lineno(node)
  934.         aug_node = wrap_aug(node.node)
  935.         self.visit(aug_node, "load")
  936.         self.visit(node.expr)
  937.         self.emit(self._augmented_opcode[node.op])
  938.         self.visit(aug_node, "store")
  939.  
  940.     _augmented_opcode = {
  941.         '+=' : 'INPLACE_ADD',
  942.         '-=' : 'INPLACE_SUBTRACT',
  943.         '*=' : 'INPLACE_MULTIPLY',
  944.         '/=' : 'INPLACE_DIVIDE',
  945.         '//=': 'INPLACE_FLOOR_DIVIDE',
  946.         '%=' : 'INPLACE_MODULO',
  947.         '**=': 'INPLACE_POWER',
  948.         '>>=': 'INPLACE_RSHIFT',
  949.         '<<=': 'INPLACE_LSHIFT',
  950.         '&=' : 'INPLACE_AND',
  951.         '^=' : 'INPLACE_XOR',
  952.         '|=' : 'INPLACE_OR',
  953.         }
  954.  
  955.     def visitAugName(self, node, mode):
  956.         if mode == "load":
  957.             self.loadName(node.name)
  958.         elif mode == "store":
  959.             self.storeName(node.name)
  960.  
  961.     def visitAugGetattr(self, node, mode):
  962.         if mode == "load":
  963.             self.visit(node.expr)
  964.             self.emit('DUP_TOP')
  965.             self.emit('LOAD_ATTR', self.mangle(node.attrname))
  966.         elif mode == "store":
  967.             self.emit('ROT_TWO')
  968.             self.emit('STORE_ATTR', self.mangle(node.attrname))
  969.  
  970.     def visitAugSlice(self, node, mode):
  971.         if mode == "load":
  972.             self.visitSlice(node, 1)
  973.         elif mode == "store":
  974.             slice = 0
  975.             if node.lower:
  976.                 slice = slice | 1
  977.             if node.upper:
  978.                 slice = slice | 2
  979.             if slice == 0:
  980.                 self.emit('ROT_TWO')
  981.             elif slice == 3:
  982.                 self.emit('ROT_FOUR')
  983.             else:
  984.                 self.emit('ROT_THREE')
  985.             self.emit('STORE_SLICE+%d' % slice)
  986.  
  987.     def visitAugSubscript(self, node, mode):
  988.         if len(node.subs) > 1:
  989.             raise SyntaxError, "augmented assignment to tuple is not possible"
  990.         if mode == "load":
  991.             self.visitSubscript(node, 1)
  992.         elif mode == "store":
  993.             self.emit('ROT_THREE')
  994.             self.emit('STORE_SUBSCR')
  995.  
  996.     def visitExec(self, node):
  997.         self.visit(node.expr)
  998.         if node.locals is None:
  999.             self.emit('LOAD_CONST', None)
  1000.         else:
  1001.             self.visit(node.locals)
  1002.         if node.globals is None:
  1003.             self.emit('DUP_TOP')
  1004.         else:
  1005.             self.visit(node.globals)
  1006.         self.emit('EXEC_STMT')
  1007.  
  1008.     def visitCallFunc(self, node):
  1009.         pos = 0
  1010.         kw = 0
  1011.         self.set_lineno(node)
  1012.         self.visit(node.node)
  1013.         for arg in node.args:
  1014.             self.visit(arg)
  1015.             if isinstance(arg, ast.Keyword):
  1016.                 kw = kw + 1
  1017.             else:
  1018.                 pos = pos + 1
  1019.         if node.star_args is not None:
  1020.             self.visit(node.star_args)
  1021.         if node.dstar_args is not None:
  1022.             self.visit(node.dstar_args)
  1023.         have_star = node.star_args is not None
  1024.         have_dstar = node.dstar_args is not None
  1025.         opcode = callfunc_opcode_info[have_star, have_dstar]
  1026.         self.emit(opcode, kw << 8 | pos)
  1027.  
  1028.     def visitPrint(self, node, newline=0):
  1029.         self.set_lineno(node)
  1030.         if node.dest:
  1031.             self.visit(node.dest)
  1032.         for child in node.nodes:
  1033.             if node.dest:
  1034.                 self.emit('DUP_TOP')
  1035.             self.visit(child)
  1036.             if node.dest:
  1037.                 self.emit('ROT_TWO')
  1038.                 self.emit('PRINT_ITEM_TO')
  1039.             else:
  1040.                 self.emit('PRINT_ITEM')
  1041.         if node.dest and not newline:
  1042.             self.emit('POP_TOP')
  1043.  
  1044.     def visitPrintnl(self, node):
  1045.         self.visitPrint(node, newline=1)
  1046.         if node.dest:
  1047.             self.emit('PRINT_NEWLINE_TO')
  1048.         else:
  1049.             self.emit('PRINT_NEWLINE')
  1050.  
  1051.     def visitReturn(self, node):
  1052.         self.set_lineno(node)
  1053.         self.visit(node.value)
  1054.         self.emit('RETURN_VALUE')
  1055.  
  1056.     def visitYield(self, node):
  1057.         self.set_lineno(node)
  1058.         self.visit(node.value)
  1059.         self.emit('YIELD_VALUE')
  1060.  
  1061.     # slice and subscript stuff
  1062.  
  1063.     def visitSlice(self, node, aug_flag=None):
  1064.         # aug_flag is used by visitAugSlice
  1065.         self.visit(node.expr)
  1066.         slice = 0
  1067.         if node.lower:
  1068.             self.visit(node.lower)
  1069.             slice = slice | 1
  1070.         if node.upper:
  1071.             self.visit(node.upper)
  1072.             slice = slice | 2
  1073.         if aug_flag:
  1074.             if slice == 0:
  1075.                 self.emit('DUP_TOP')
  1076.             elif slice == 3:
  1077.                 self.emit('DUP_TOPX', 3)
  1078.             else:
  1079.                 self.emit('DUP_TOPX', 2)
  1080.         if node.flags == 'OP_APPLY':
  1081.             self.emit('SLICE+%d' % slice)
  1082.         elif node.flags == 'OP_ASSIGN':
  1083.             self.emit('STORE_SLICE+%d' % slice)
  1084.         elif node.flags == 'OP_DELETE':
  1085.             self.emit('DELETE_SLICE+%d' % slice)
  1086.         else:
  1087.             print "weird slice", node.flags
  1088.             raise
  1089.  
  1090.     def visitSubscript(self, node, aug_flag=None):
  1091.         self.visit(node.expr)
  1092.         for sub in node.subs:
  1093.             self.visit(sub)
  1094.         if aug_flag:
  1095.             self.emit('DUP_TOPX', 2)
  1096.         if len(node.subs) > 1:
  1097.             self.emit('BUILD_TUPLE', len(node.subs))
  1098.         if node.flags == 'OP_APPLY':
  1099.             self.emit('BINARY_SUBSCR')
  1100.         elif node.flags == 'OP_ASSIGN':
  1101.             self.emit('STORE_SUBSCR')
  1102.         elif node.flags == 'OP_DELETE':
  1103.             self.emit('DELETE_SUBSCR')
  1104.  
  1105.     # binary ops
  1106.  
  1107.     def binaryOp(self, node, op):
  1108.         self.visit(node.left)
  1109.         self.visit(node.right)
  1110.         self.emit(op)
  1111.  
  1112.     def visitAdd(self, node):
  1113.         return self.binaryOp(node, 'BINARY_ADD')
  1114.  
  1115.     def visitSub(self, node):
  1116.         return self.binaryOp(node, 'BINARY_SUBTRACT')
  1117.  
  1118.     def visitMul(self, node):
  1119.         return self.binaryOp(node, 'BINARY_MULTIPLY')
  1120.  
  1121.     def visitDiv(self, node):
  1122.         return self.binaryOp(node, self._div_op)
  1123.  
  1124.     def visitFloorDiv(self, node):
  1125.         return self.binaryOp(node, 'BINARY_FLOOR_DIVIDE')
  1126.  
  1127.     def visitMod(self, node):
  1128.         return self.binaryOp(node, 'BINARY_MODULO')
  1129.  
  1130.     def visitPower(self, node):
  1131.         return self.binaryOp(node, 'BINARY_POWER')
  1132.  
  1133.     def visitLeftShift(self, node):
  1134.         return self.binaryOp(node, 'BINARY_LSHIFT')
  1135.  
  1136.     def visitRightShift(self, node):
  1137.         return self.binaryOp(node, 'BINARY_RSHIFT')
  1138.  
  1139.     # unary ops
  1140.  
  1141.     def unaryOp(self, node, op):
  1142.         self.visit(node.expr)
  1143.         self.emit(op)
  1144.  
  1145.     def visitInvert(self, node):
  1146.         return self.unaryOp(node, 'UNARY_INVERT')
  1147.  
  1148.     def visitUnarySub(self, node):
  1149.         return self.unaryOp(node, 'UNARY_NEGATIVE')
  1150.  
  1151.     def visitUnaryAdd(self, node):
  1152.         return self.unaryOp(node, 'UNARY_POSITIVE')
  1153.  
  1154.     def visitUnaryInvert(self, node):
  1155.         return self.unaryOp(node, 'UNARY_INVERT')
  1156.  
  1157.     def visitNot(self, node):
  1158.         return self.unaryOp(node, 'UNARY_NOT')
  1159.  
  1160.     def visitBackquote(self, node):
  1161.         return self.unaryOp(node, 'UNARY_CONVERT')
  1162.  
  1163.     # bit ops
  1164.  
  1165.     def bitOp(self, nodes, op):
  1166.         self.visit(nodes[0])
  1167.         for node in nodes[1:]:
  1168.             self.visit(node)
  1169.             self.emit(op)
  1170.  
  1171.     def visitBitand(self, node):
  1172.         return self.bitOp(node.nodes, 'BINARY_AND')
  1173.  
  1174.     def visitBitor(self, node):
  1175.         return self.bitOp(node.nodes, 'BINARY_OR')
  1176.  
  1177.     def visitBitxor(self, node):
  1178.         return self.bitOp(node.nodes, 'BINARY_XOR')
  1179.  
  1180.     # object constructors
  1181.  
  1182.     def visitEllipsis(self, node):
  1183.         self.emit('LOAD_CONST', Ellipsis)
  1184.  
  1185.     def visitTuple(self, node):
  1186.         self.set_lineno(node)
  1187.         for elt in node.nodes:
  1188.             self.visit(elt)
  1189.         self.emit('BUILD_TUPLE', len(node.nodes))
  1190.  
  1191.     def visitList(self, node):
  1192.         self.set_lineno(node)
  1193.         for elt in node.nodes:
  1194.             self.visit(elt)
  1195.         self.emit('BUILD_LIST', len(node.nodes))
  1196.  
  1197.     def visitSliceobj(self, node):
  1198.         for child in node.nodes:
  1199.             self.visit(child)
  1200.         self.emit('BUILD_SLICE', len(node.nodes))
  1201.  
  1202.     def visitDict(self, node):
  1203.         self.set_lineno(node)
  1204.         self.emit('BUILD_MAP', 0)
  1205.         for k, v in node.items:
  1206.             self.emit('DUP_TOP')
  1207.             self.visit(k)
  1208.             self.visit(v)
  1209.             self.emit('ROT_THREE')
  1210.             self.emit('STORE_SUBSCR')
  1211.  
  1212. class NestedScopeMixin:
  1213.     """Defines initClass() for nested scoping (Python 2.2-compatible)"""
  1214.     def initClass(self):
  1215.         self.__class__.NameFinder = LocalNameFinder
  1216.         self.__class__.FunctionGen = FunctionCodeGenerator
  1217.         self.__class__.ClassGen = ClassCodeGenerator
  1218.  
  1219. class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator):
  1220.     __super_init = CodeGenerator.__init__
  1221.  
  1222.     scopes = None
  1223.  
  1224.     def __init__(self, tree):
  1225.         self.graph = pyassem.PyFlowGraph("<module>", tree.filename)
  1226.         self.futures = future.find_futures(tree)
  1227.         self.__super_init()
  1228.         walk(tree, self)
  1229.  
  1230.     def get_module(self):
  1231.         return self
  1232.  
  1233. class ExpressionCodeGenerator(NestedScopeMixin, CodeGenerator):
  1234.     __super_init = CodeGenerator.__init__
  1235.  
  1236.     scopes = None
  1237.     futures = ()
  1238.  
  1239.     def __init__(self, tree):
  1240.         self.graph = pyassem.PyFlowGraph("<expression>", tree.filename)
  1241.         self.__super_init()
  1242.         walk(tree, self)
  1243.  
  1244.     def get_module(self):
  1245.         return self
  1246.  
  1247. class InteractiveCodeGenerator(NestedScopeMixin, CodeGenerator):
  1248.  
  1249.     __super_init = CodeGenerator.__init__
  1250.  
  1251.     scopes = None
  1252.     futures = ()
  1253.  
  1254.     def __init__(self, tree):
  1255.         self.graph = pyassem.PyFlowGraph("<interactive>", tree.filename)
  1256.         self.__super_init()
  1257.         self.set_lineno(tree)
  1258.         walk(tree, self)
  1259.         self.emit('RETURN_VALUE')
  1260.  
  1261.     def get_module(self):
  1262.         return self
  1263.  
  1264.     def visitDiscard(self, node):
  1265.         # XXX Discard means it's an expression.  Perhaps this is a bad
  1266.         # name.
  1267.         self.visit(node.expr)
  1268.         self.emit('PRINT_EXPR')
  1269.  
  1270. class AbstractFunctionCode:
  1271.     optimized = 1
  1272.     lambdaCount = 0
  1273.  
  1274.     def __init__(self, func, scopes, isLambda, class_name, mod):
  1275.         self.class_name = class_name
  1276.         self.module = mod
  1277.         if isLambda:
  1278.             klass = FunctionCodeGenerator
  1279.             name = "<lambda.%d>" % klass.lambdaCount
  1280.             klass.lambdaCount = klass.lambdaCount + 1
  1281.         else:
  1282.             name = func.name
  1283.  
  1284.         args, hasTupleArg = generateArgList(func.argnames)
  1285.         self.graph = pyassem.PyFlowGraph(name, func.filename, args,
  1286.                                          optimized=1)
  1287.         self.isLambda = isLambda
  1288.         self.super_init()
  1289.  
  1290.         if not isLambda and func.doc:
  1291.             self.setDocstring(func.doc)
  1292.  
  1293.         lnf = walk(func.code, self.NameFinder(args), verbose=0)
  1294.         self.locals.push(lnf.getLocals())
  1295.         if func.varargs:
  1296.             self.graph.setFlag(CO_VARARGS)
  1297.         if func.kwargs:
  1298.             self.graph.setFlag(CO_VARKEYWORDS)
  1299.         self.set_lineno(func)
  1300.         if hasTupleArg:
  1301.             self.generateArgUnpack(func.argnames)
  1302.  
  1303.     def get_module(self):
  1304.         return self.module
  1305.  
  1306.     def finish(self):
  1307.         self.graph.startExitBlock()
  1308.         if not self.isLambda:
  1309.             self.emit('LOAD_CONST', None)
  1310.         self.emit('RETURN_VALUE')
  1311.  
  1312.     def generateArgUnpack(self, args):
  1313.         for i in range(len(args)):
  1314.             arg = args[i]
  1315.             if type(arg) == types.TupleType:
  1316.                 self.emit('LOAD_FAST', '.%d' % (i * 2))
  1317.                 self.unpackSequence(arg)
  1318.  
  1319.     def unpackSequence(self, tup):
  1320.         if VERSION > 1:
  1321.             self.emit('UNPACK_SEQUENCE', len(tup))
  1322.         else:
  1323.             self.emit('UNPACK_TUPLE', len(tup))
  1324.         for elt in tup:
  1325.             if type(elt) == types.TupleType:
  1326.                 self.unpackSequence(elt)
  1327.             else:
  1328.                 self._nameOp('STORE', elt)
  1329.  
  1330.     unpackTuple = unpackSequence
  1331.  
  1332. class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
  1333.                             CodeGenerator):
  1334.     super_init = CodeGenerator.__init__ # call be other init
  1335.     scopes = None
  1336.  
  1337.     __super_init = AbstractFunctionCode.__init__
  1338.  
  1339.     def __init__(self, func, scopes, isLambda, class_name, mod):
  1340.         self.scopes = scopes
  1341.         self.scope = scopes[func]
  1342.         self.__super_init(func, scopes, isLambda, class_name, mod)
  1343.         self.graph.setFreeVars(self.scope.get_free_vars())
  1344.         self.graph.setCellVars(self.scope.get_cell_vars())
  1345.         if self.scope.generator is not None:
  1346.             self.graph.setFlag(CO_GENERATOR)
  1347.  
  1348. class GenExprCodeGenerator(NestedScopeMixin, AbstractFunctionCode,
  1349.                            CodeGenerator):
  1350.     super_init = CodeGenerator.__init__ # call be other init
  1351.     scopes = None
  1352.  
  1353.     __super_init = AbstractFunctionCode.__init__
  1354.  
  1355.     def __init__(self, gexp, scopes, class_name, mod):
  1356.         self.scopes = scopes
  1357.         self.scope = scopes[gexp]
  1358.         self.__super_init(gexp, scopes, 1, class_name, mod)
  1359.         self.graph.setFreeVars(self.scope.get_free_vars())
  1360.         self.graph.setCellVars(self.scope.get_cell_vars())
  1361.         self.graph.setFlag(CO_GENERATOR)
  1362.  
  1363. class AbstractClassCode:
  1364.  
  1365.     def __init__(self, klass, scopes, module):
  1366.         self.class_name = klass.name
  1367.         self.module = module
  1368.         self.graph = pyassem.PyFlowGraph(klass.name, klass.filename,
  1369.                                            optimized=0, klass=1)
  1370.         self.super_init()
  1371.         lnf = walk(klass.code, self.NameFinder(), verbose=0)
  1372.         self.locals.push(lnf.getLocals())
  1373.         self.graph.setFlag(CO_NEWLOCALS)
  1374.         if klass.doc:
  1375.             self.setDocstring(klass.doc)
  1376.  
  1377.     def get_module(self):
  1378.         return self.module
  1379.  
  1380.     def finish(self):
  1381.         self.graph.startExitBlock()
  1382.         self.emit('LOAD_LOCALS')
  1383.         self.emit('RETURN_VALUE')
  1384.  
  1385. class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator):
  1386.     super_init = CodeGenerator.__init__
  1387.     scopes = None
  1388.  
  1389.     __super_init = AbstractClassCode.__init__
  1390.  
  1391.     def __init__(self, klass, scopes, module):
  1392.         self.scopes = scopes
  1393.         self.scope = scopes[klass]
  1394.         self.__super_init(klass, scopes, module)
  1395.         self.graph.setFreeVars(self.scope.get_free_vars())
  1396.         self.graph.setCellVars(self.scope.get_cell_vars())
  1397.         self.set_lineno(klass)
  1398.         self.emit("LOAD_GLOBAL", "__name__")
  1399.         self.storeName("__module__")
  1400.         if klass.doc:
  1401.             self.emit("LOAD_CONST", klass.doc)
  1402.             self.storeName('__doc__')
  1403.  
  1404. def generateArgList(arglist):
  1405.     """Generate an arg list marking TupleArgs"""
  1406.     args = []
  1407.     extra = []
  1408.     count = 0
  1409.     for i in range(len(arglist)):
  1410.         elt = arglist[i]
  1411.         if type(elt) == types.StringType:
  1412.             args.append(elt)
  1413.         elif type(elt) == types.TupleType:
  1414.             args.append(TupleArg(i * 2, elt))
  1415.             extra.extend(misc.flatten(elt))
  1416.             count = count + 1
  1417.         else:
  1418.             raise ValueError, "unexpect argument type:", elt
  1419.     return args + extra, count
  1420.  
  1421. def findOp(node):
  1422.     """Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
  1423.     v = OpFinder()
  1424.     walk(node, v, verbose=0)
  1425.     return v.op
  1426.  
  1427. class OpFinder:
  1428.     def __init__(self):
  1429.         self.op = None
  1430.     def visitAssName(self, node):
  1431.         if self.op is None:
  1432.             self.op = node.flags
  1433.         elif self.op != node.flags:
  1434.             raise ValueError, "mixed ops in stmt"
  1435.     visitAssAttr = visitAssName
  1436.     visitSubscript = visitAssName
  1437.  
  1438. class Delegator:
  1439.     """Base class to support delegation for augmented assignment nodes
  1440.  
  1441.     To generator code for augmented assignments, we use the following
  1442.     wrapper classes.  In visitAugAssign, the left-hand expression node
  1443.     is visited twice.  The first time the visit uses the normal method
  1444.     for that node .  The second time the visit uses a different method
  1445.     that generates the appropriate code to perform the assignment.
  1446.     These delegator classes wrap the original AST nodes in order to
  1447.     support the variant visit methods.
  1448.     """
  1449.     def __init__(self, obj):
  1450.         self.obj = obj
  1451.  
  1452.     def __getattr__(self, attr):
  1453.         return getattr(self.obj, attr)
  1454.  
  1455. class AugGetattr(Delegator):
  1456.     pass
  1457.  
  1458. class AugName(Delegator):
  1459.     pass
  1460.  
  1461. class AugSlice(Delegator):
  1462.     pass
  1463.  
  1464. class AugSubscript(Delegator):
  1465.     pass
  1466.  
  1467. wrapper = {
  1468.     ast.Getattr: AugGetattr,
  1469.     ast.Name: AugName,
  1470.     ast.Slice: AugSlice,
  1471.     ast.Subscript: AugSubscript,
  1472.     }
  1473.  
  1474. def wrap_aug(node):
  1475.     return wrapper[node.__class__](node)
  1476.  
  1477. if __name__ == "__main__":
  1478.     for file in sys.argv[1:]:
  1479.         compileFile(file)
  1480.